from utils import AppContext
from utils import ReqContext
from utils import RenderContext
from mako.lookup import TemplateLookup
from curen.utils.url import urldecode
from curen.utils.http import decode_post
from helloweb.cookies import Cookie
from curen.utils.classloader import load_class
import urllib
import helloweb
import traceback
from sys import path as syspath
class WsgiApp:
    def main(self, config):
        self.config = config
        self.init_members(config)
        self.setup_app(config)
    
    def init_members(self, config):
        self.modules = {}
        self.encode = config.get('page', 'encode')
        
    def setup_app(self, config):
        ctx = AppContext()
        self.app_context = ctx
        helloweb.app_context = ctx
        ctx.template_engine = TemplateLookup(directories=['.'],
                                    module_directory='tmp/mako_modules',
                                    input_encoding=self.encode, output_encoding=self.encode, encoding_errors='replace')
        syspath.append('../lib')
        ctx.lib = __import__('lib')
        ctx.app = __import__('app')
        ctx.req_cnt = 0
        ctx.app.app_started(config)
    
    def __call__(self, environ, start_response):
        print '__call__'
        #for k, v in environ.items():
        #   print k, '-:-', v
        
        #print environ['wsgi.input'].read()
        #print '_call_'
        #try:       
        self.app_context.req_cnt+=1
        self.setup_req_context(environ, start_response)

        self.setup_render_context(environ, start_response)

        self.setup_session(environ, start_response)

        self.app_context.app.app_request(environ)

        self.dispatch(environ, start_response)
              
            
        status, headers, output = self.response(environ, start_response)
        newheaders = []
        for k,v in headers:
            v = v.encode(self.encode)
            newheaders.append((k, v))
        start_response(status, newheaders)

        return output or ''
        
        #except:
            #traceback.print_exc()
            #return ['error']
        
    def response(self, environ, start_response):
        req_ctx = environ['helloweb.reqctx']
        status = req_ctx.status
        headers = req_ctx.headers
        output = req_ctx.output
        
        headers.extend(environ['helloweb.reqctx'].cookie.to_headers())
        return status, headers, output 
    
    def setup_session(self, environ, start_response):
        pass
    
    def setup_req_context(self, environ, start_response):
        ctx = ReqContext()
        environ['helloweb.reqctx'] = ctx
        ctx.wsgiapp = self
        ctx.environ = environ
        ctx.start_response = start_response
        ctx.app_context = self.app_context
        ctx.lib = self.app_context.lib
        ctx.app = self.app_context.app
        #response
        ctx.output = []
        
        #
        ctx.status = '200 OK'
        ctx.headers = []
        
        #get query
        get_query_string = environ['QUERY_STRING']
        get_params = urldecode(get_query_string, self.encode)
        ctx.get_params = get_params
        
        #post query
        HTTP_CONTENT_TYPE = environ.has_key('HTTP_CONTENT_TYPE') and environ['HTTP_CONTENT_TYPE'] or None
        content = HTTP_CONTENT_TYPE and environ['wsgi.input'].read() or None
        post_params = decode_post(HTTP_CONTENT_TYPE, content, self.encode);
        ctx.post_params = post_params
        ctx.input = content
        #wsgiinput = environ['wsgi.input'].read()
        
        #post_query_string = urllib.unquote_plus(wsgiinput)
        #post_params = urldecode(post_query_string, self.encode);
        #ctx.post_params = post_params
        
        #cookie
        cookie = Cookie()
        cookie_string = environ.get('HTTP_COOKIE')
        
        if cookie_string:cookie.load(cookie_string)
        ctx.cookie = cookie
        
        #session
        session_cls = self.config.get('server','session')
        
        session_cls = load_class(session_cls)
        session = session_cls()
        session.config(self.config)
        session.start(cookie, ctx)
        ctx.session = session
        
    def setup_render_context(self, environ, start_response):
        ctx = RenderContext()
        reqctx = environ['helloweb.reqctx']
        reqctx.d = ctx
        
    def dispatch(self, environ, start_response):
        self.routing_map(environ)
        reqctx = environ['helloweb.reqctx']
        reqctx.dispatch()
    

    def routing_map(self, environ):
        path_info = environ['PATH_INFO']
        print 'path_info ', path_info
        done = False
        app_context = self.app_context
        if hasattr(app_context.app, 'routing_map'):
            (done, modulename, action, args) = app_context.app.routing_map(environ, path_info)
        
        if not done:
            modulename = 'main'
            action = 'index'
            lside = 0
            if path_info[0] == '/' : lside = 1
            if path_info[len(path_info) - 1] == '/' : 
                path_info = path_info[lside:-1]
            else:
                path_info = path_info[lside:]
	    print path_info
            paths = path_info.split('/')

            if len(paths) >= 1 and paths[0] != '' :modulename = paths[0]
            if len(paths) >= 2:action     = paths[1]
            _args = paths[2:]
            
            args = [arg.decode(self.encode) for arg in _args]
        
        reqctx = environ['helloweb.reqctx']
        
        reqctx.action = action
        reqctx.args = args
        
        _names = [modulename, 'def']
        for _name in _names:
            reqctx.modulename = _name
            try:
                if self.modules.has_key(_name):
                    module = self.modules[_name]
                    reload(module)
                    reqctx.module = module
                else:
                    module = __import__("module.%s.controller"%_name, globals(), locals(), ['%s.controller'%_name])
                        
                    self.modules[_name] = module            
                    reqctx.module = module 
                if _name == 'def':
                    reqctx.args.append(modulename)
                break
            except:
                print 'load error'
                print traceback.format_exc()
                print 'can not load module ', _name
        
        
